#pragma once
#include <vector>
#include <string>
#include <iostream>
#include <mutex>
#include <semaphore.h>
// 本文件用于提供环形队列所需要的接口
const int size = 5;

template <typename T>
class ringQueue
{
public:
    ringQueue(int num = size)
        : _cap(num)
    {
        _rq.resize(num);
        _p_step = _c_step = 0;
        // int sem_init(sem_t *sem, int pshared, unsigned int value);
        // pshared:0表示线程间共享，非零表示进程间共享
        // value：信号量初始值
        sem_init(&_space_sem, 0, num);
        sem_init(&_data_sem, 0, 0);
        pthread_mutex_init(&_p_mutex, nullptr);
        pthread_mutex_init(&_c_mutex, nullptr);
    }

    // template<typename T>
    void push(T &data)
    {
        sem_wait(&_space_sem); // 空间资源减少，P操作
        pthread_mutex_lock(&_p_mutex);//多生产，保证生产者与生产者之间的互斥关系
        _rq[_p_step++] = data;
        _p_step %= _cap; // 保证环形队列的特性
        pthread_mutex_unlock(&_p_mutex);
        sem_post(&_data_sem); // 数据资源增加，V操作
    }
    void pop(T &data)
    {
        sem_wait(&_data_sem);
        pthread_mutex_unlock(&_c_mutex);//多生产，保证消费者与消费者之间的互斥关系
        data = _rq[_c_step++]; // 消费者往后走说明前面那个空间的数据被拿走，不需要销毁
        _c_step %= _cap;
        pthread_mutex_unlock(&_c_mutex);
        sem_post(&_space_sem);
    }

private:
    std::vector<T> _rq;
    int _cap;
    int _p_step;      // 生产者数组中所在位置
    int _c_step;      // 消费者数组中所在位置
    sem_t _space_sem; // 生产者信号量
    sem_t _data_sem;  // 消费者信号量
    pthread_mutex_t _p_mutex;
    pthread_mutex_t _c_mutex;
};